home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 July / EnigmA AMIGA RUN 20 (1997)(G.R. Edizioni)(IT)[!][issue 1997-07 & 08][EAR-CD IV].iso / earcd / dev / mui / muiplusp.lha / Rexx / CreateHeader.rexx next >
OS/2 REXX Batch file  |  1997-03-23  |  20KB  |  641 lines

  1. /* Creates C++ header form inheritance file and muidefs files */
  2.  
  3. /* The following settings adjust the output of the header file */
  4.  
  5. parse arg outputDir
  6.  
  7. headerName = outputDir'MUI.hpp'         /* Name of file generated */
  8. libName = outputDir'MUI.cpp'            /* Link lib source file name */
  9. linkLibName = outputDir'libMUIPlusPlus.a'
  10. inlinesFileName = 't:inline'
  11. obsoleteDeclarationsFileName = 't:ObsoleteDeclarations'
  12. obsoleteInlinesFileName = 't:ObsoleteInlines'
  13. debugName = 'MUIPP_DEBUG'               /* #define needed to turn on debugging */
  14. obsoleteName = 'MUI_OBSOLETE'           /* #define needed to include
  15.                                            obsolete methods and attributes */
  16. inlineName = 'MUIPP_NOINLINES'          /* #define needed to not make methods
  17.                                            and attributes inline */
  18. classPrefix = 'CMUI_'                   /* Prefix before each class name */
  19. startVarArgs = 'StartVarArgs'           /* Class name for first argument of
  20.                                            a variable arguments method */
  21. tab = '09'x
  22. nl = '0a'x             /* New line character */
  23. indent = tab           /* Character used for indenting */
  24. commentLineLength = 74 /* Set this to the width of comment before each class */
  25.  
  26. startCommentline = '/*'
  27. endCommentLine = ''
  28. do i = 1 to commentlinelength
  29.     startCommentline = startCommentline'*'
  30.     endCommentLine = endCommentLine'*'
  31. end
  32. endCommentLine = endCommentLine'*/'
  33.  
  34. if ~open(inheritance,"inheritance",'read') then do
  35.     call Error("Could not open inheritance file")
  36. end
  37.  
  38. if ~open(output,headerName,'write') then do
  39.     call Error("Could not create header file: "headerName)
  40. end
  41.  
  42. if ~open(lib,libName,'write') then do
  43.     call Error("Could not create library source file: "libName)
  44. end
  45.  
  46. if ~open(inlinesFile,inlinesFileName,'write') then do
  47.     call Error("Could not create temporary inline file: "inlinesFileName)
  48. end
  49.  
  50. if ~open(obsoleteInlinesFile,obsoleteInlinesFileName,'write') then do
  51.     call Error("Could not create temporary obsolete inline file: "obsoleteinlinesFileName)
  52. end
  53.  
  54. headerEnd = ''
  55.  
  56. call AppendFile(lib,"LibStart")
  57.  
  58. /* Scan Inheritance file and create class definitions */
  59.  
  60. do while ~eof(inheritance)
  61.  
  62.     line = readln(inheritance)
  63.  
  64.     /* Check if line is a command to include another file or comment
  65.        file */
  66.  
  67.     action = strip(word(line,1))
  68.  
  69.     if action = 'include' then do
  70.         call AppendFile(output,strip(word(line,2)))
  71.         iterate
  72.     end
  73.  
  74.     else if action = 'comment' then do
  75.         call AppendFileCommented(output,strip(word(line,2)))
  76.         iterate
  77.     end
  78.  
  79.     else if action = 'end' then do
  80.         headerEnd = strip(word(line,2))
  81.         iterate
  82.     end
  83.  
  84.     if action = 'abstract' then do
  85.         line = substr(line,wordindex(line,2))
  86.         abstractClass = 'y'
  87.     end
  88.  
  89.     else abstractClass = 'n'
  90.  
  91.     /* Ignore comments */
  92.  
  93.     if substr(line,1,1) = ';' then iterate
  94.  
  95.     /* Line is a class name and inheritence list so generate constructors
  96.        and member functions for class */
  97.  
  98.     className = strip(word(line,1))
  99.  
  100.     if className = '' then iterate
  101.  
  102.     cppClassName = classPrefix || className
  103.  
  104.     /* Get all classes that this inherits from */
  105.  
  106.     bases.0 = words(line) - 1    /* Number of classes to inherit from */
  107.  
  108.     do i = 1 to bases.0
  109.         bases.i = strip(word(line,i + 1))
  110.     end
  111.  
  112.     call writech(stdout,"Writing" cppClassName "class definition...")
  113.  
  114.     /* Write comment that preceeds each class */
  115.  
  116.     call writeln(output,startCommentLine)
  117.     call writeln(output,'**'center(cppClassName 'class definition',commentlinelength))
  118.     call writeln(output,endCommentLine || nl)
  119.  
  120.     call writech(output,"class" cppClassName)
  121.  
  122.     /* Write the primary class that it inherits from */
  123.  
  124.     if bases.0 ~= 0 then do
  125.         call writech(output," : public" classPrefix || bases.1)
  126.     end
  127.  
  128.     call writeln(output,nl"{"nl"public:")
  129.  
  130.     /* Find out what tags must be specified when constructing the object */
  131.  
  132.     required.0 = 0
  133.  
  134.     if exists(className'.required') then do
  135.         if ~open(requiredFile,className'.required','read') then do
  136.             say "Could not open" className".required"
  137.             return
  138.         end
  139.  
  140.         i = 0
  141.  
  142.         do while ~eof(requiredFile)
  143.             tagRequired = strip(readln(requiredFile))
  144.             if tagRequired = '' then iterate
  145.             i = i + 1
  146.             required.i = tagRequired
  147.         end
  148.  
  149.         required.0 = i
  150.         call close(requiredFile)
  151.     end
  152.  
  153.     /* Write the constructors if not an abstract class */
  154.  
  155.     if abstractClass = 'n' then do
  156.  
  157.         /* Constructor that declares a NULL object */
  158.  
  159.         call writeln(output,indent || cppClassName '(void)')
  160.         if bases.0 ~= 0 then do
  161.             call writeln(output,indent":" classPrefix || bases.1 "()")
  162.         end
  163.         call writeln(output,indent'{')
  164.         call writeln(output,indent'}'nl)
  165.  
  166.         /* Constructors that use tags. We first check to ensure that some
  167.            tags do exist for this class as the details are held in a
  168.            .muidefs file. If this file does not exist then there are no
  169.            tags for this class defined. The .muidefs file can be generated
  170.            from the autodocs using DocToDef.rexx */
  171.  
  172.         if exists(className'.muidefs') then do
  173.  
  174.             /* Constructor that use "struct TagItem *" */
  175.  
  176.             call writeln(output,indent || cppClassName '(struct TagItem *tags)')
  177.  
  178.             if bases.0 ~= 0 then do
  179.                 call writeln(output,indent":" classPrefix || bases.1 "()")
  180.             end
  181.  
  182.             call writeln(output,indent'{')
  183.  
  184.             if required.0 ~= 0 then do
  185.                 call writeln(output,"#ifdef "debugName)
  186.                 call writech(output,indent || indent'_CheckTagsSpecified ("'cppClassName'", tags')
  187.                 do i = 1 to required.0
  188.                     call writech(output, ', 'required.i', "'required.i'"')
  189.                 end
  190.                 call writeln(output,", TAG_DONE);")
  191.                 call writeln(output,"#endif")
  192.             end
  193.  
  194.             call writeln(output,indent || indent'object = MUI_NewObjectA (MUIC_'className', tags);')
  195.  
  196.             call writeln(output,"#ifdef "debugName)
  197.             call writeln(output,indent || indent'if (object == NULL)')
  198.             call writeln(output,indent || indent || indent'_MUIPPWarning ("Could not create a 'cppClassName 'object\n");')
  199.             call writeln(output,"#endif")
  200.  
  201.             call writeln(output,indent'}'nl)
  202.  
  203.             /* Constructor that uses Tags */
  204.  
  205.             call writeln(output,indent || cppClassName '(Tag tag1, ...)')
  206.  
  207.             if bases.0 ~= 0 then do
  208.                 call writeln(output,indent":" classPrefix || bases.1 "()")
  209.             end
  210.  
  211.             call writeln(output,indent'{')
  212.  
  213.             if required.0 ~= 0 then do
  214.                 call writeln(output,"#ifdef "debugName)
  215.                 call writech(output,indent || indent'_CheckTagsSpecified ("'cppClassName'", (struct TagItem *)&tag1')
  216.                 do i = 1 to required.0
  217.                     call writech(output, ', 'required.i', "'required.i'"')
  218.                 end
  219.                 call writeln(output,", TAG_DONE);")
  220.                 call writeln(output,"#endif")
  221.             end
  222.  
  223.             call writeln(output,indent || indent'object = MUI_NewObjectA (MUIC_'className', (struct TagItem *)&tag1);')
  224.  
  225.             call writeln(output,"#ifdef "debugName)
  226.             call writeln(output,indent || indent'if (object == NULL)')
  227.             call writeln(output,indent || indent || indent'_MUIPPWarning ("Could not create a 'cppClassName 'object\n");')
  228.             call writeln(output,"#endif")
  229.  
  230.             call writeln(output,indent'}'nl)
  231.  
  232.         end
  233.  
  234.         /* Constructor that uses a BOOPSI object pointer */
  235.  
  236.         call writeln(output,indent || cppClassName '(Object * obj)')
  237.  
  238.         if bases.0 ~= 0 then do
  239.             call writeln(output,indent":" classPrefix || bases.1 "()")
  240.         end
  241.  
  242.         call writeln(output,indent'{')
  243.         call writeln(output,indent || indent'object = obj;')
  244.         call writeln(output,indent'}'nl)
  245.  
  246.         /* Constructor that uses MUI_MakeObject */
  247.  
  248.         call WriteMakeObjectConstructor(className,bases.1)
  249.  
  250.         /* Overload operator = */
  251.  
  252.         call writeln(output,indent || cppClassName '& operator = (Object * obj)')
  253.         call writeln(output,indent'{')
  254.         call writeln(output,indent || indent'object = obj;')
  255.         call writeln(output,indent || indent'return *this;')
  256.         call writeln(output,indent'}'nl)
  257.  
  258.     end
  259.  
  260.     /* Include other public stuff related to this class if present */
  261.  
  262.     if exists(className'.public') then do
  263.         call AppendFileIndented(output,className'.public')
  264.     end
  265.  
  266.     /* Create file to store obsolete declarations for this class */
  267.  
  268.     if ~open(obsoleteDeclarationsFile,obsoleteDeclarationsFileName,'write') then do
  269.         call Error("Could not create temporary obsolete inline file: "obsoleteDeclarationsFileName)
  270.     end
  271.  
  272.     obsoleteDeclarationsExist = 'n'
  273.  
  274.     /* Write attributes and methods for classes this inherits from other
  275.        than the first one */
  276.  
  277.     do i = 2 to bases.0
  278.         call WriteAttributesAndMethods(className,bases.i)
  279.     end
  280.  
  281.     /* Write this class's specific attribs. and methods */
  282.  
  283.     call WriteAttributesAndMethods(className,'')
  284.  
  285.     call close(obsoleteDeclarationsFile)
  286.  
  287.     /* Write the obsolete declarations */
  288.  
  289.     if obsoleteDeclarationsExist = 'y' then do
  290.         call writeln(output,'#ifdef' obsoleteName)
  291.         call AppendFile(output,obsoleteDeclarationsFileName)
  292.         call writeln(output,'#endif /*' obsoleteName '*/')
  293.     end
  294.  
  295.     if abstractClass = 'y' then do
  296.         writeln(output,'protected:')
  297.  
  298.         /* Constructor that declares a NULL object */
  299.  
  300.         call writeln(output,indent || cppClassName '(void)')
  301.  
  302.         if bases.0 ~= 0 then do
  303.             call writeln(output,indent":" classPrefix || bases.1 "()")
  304.         end
  305.  
  306.         call writeln(output,indent'{')
  307.         call writeln(output,indent'}'nl)
  308.     end
  309.  
  310.     call writeln(output,"};"nl)
  311.     call writeln(stdout,"done")
  312. end
  313.  
  314. /* Add inline function definitions */
  315.  
  316. call writech(stdout,"Writing inline functions....")
  317. call writeln(output,'#ifndef' inlineName || nl)
  318. call close(inlinesFile)
  319. call close(obsoleteInlinesFile)
  320. call AppendFile(output,inlinesFileName)
  321. call writeln(output,'#ifdef' obsoleteName || nl)
  322. call AppendFile(output,obsoleteInlinesFileName)
  323. call writeln(output,nl'#endif     /* 'obsoleteName'*/')
  324. call writeln(output,nl'#endif     /* 'inlineName' */')
  325. say "done"
  326.  
  327. /* Add end of header file if one has been specified */
  328.  
  329. if headerEnd ~= '' then call AppendFile(output,"HeaderEnd")
  330.  
  331. address command 'delete' inlinesFileName obsoleteInlinesFileName
  332.  
  333. call close(output)
  334. call close(lib)
  335.  
  336. say "All completed!"
  337. say "Header file:" headerName
  338. say "Link library source:" libName
  339.  
  340. exit
  341.  
  342. /* Display an error message and quit */
  343.  
  344. Error: PROCEDURE
  345.     parse arg message
  346.     say message
  347.     exit
  348. return
  349.  
  350. AppendFile: PROCEDURE
  351.     parse arg file , fileName
  352.  
  353.     if ~open(file2,fileName,'read') then do
  354.         call Error("Could not open file: " fileName)
  355.     end
  356.  
  357.     do while ~eof(file2)
  358.         call writeln(file,readln(file2))
  359.     end
  360.  
  361.     call close(file2)
  362. return
  363.  
  364. AppendFileCommented: PROCEDURE expose startCommentLine endCommentLine
  365.     parse arg file, fileName
  366.  
  367.     if ~open(file2,fileName,'read') then do
  368.         call Error("Could not open file: " fileName)
  369.     end
  370.  
  371.     call writeln(file, startCommentLine)
  372.  
  373.     do while ~eof(file2)
  374.         line = readln(file2)
  375.         if substr(line,1,1) = '*' then call writeln(file,'***'line)
  376.         else call writeln(file,'** 'line)
  377.     end
  378.  
  379.     call writeln(file, endCommentLine)
  380.  
  381.     call close(file2)
  382. return
  383.  
  384. AppendFileIndented: PROCEDURE expose indent
  385.     parse arg file , fileName
  386.  
  387.     if ~open(file2,fileName,'read') then do
  388.         call Error("Could not open file: " fileName)
  389.     end
  390.  
  391.     do while ~eof(file2)
  392.         call writeln(file,indent || readln(file2))
  393.     end
  394.  
  395.     call close(file2)
  396. return
  397.  
  398.  
  399. /* This function will create the constructor that uses MUI_MakeObject().
  400.    It will look to see if a file called className.makeobj exists. If it does
  401.    then it will read in the specification from the file and write the
  402.    constructor. */
  403.  
  404. WriteMakeObjectConstructor: PROCEDURE expose output indent nl classPrefix
  405.     parse arg className , superClassName
  406.  
  407.     cppClassName = classPrefix || className
  408.  
  409.     if exists(className'.makeobj') then do
  410.  
  411.         if ~open(makeObjFile,className'.makeobj','read') then do
  412.             Error "Could not open" className".makeobj"
  413.         end
  414.  
  415.         /* Get object type */
  416.  
  417.         objectType = strip(readln(makeObjFile))
  418.  
  419.         params = readln(makeObjFile)
  420.         i = 0
  421.  
  422.         do forever
  423.             parse var params firstparam ',' params
  424.  
  425.            if firstparam = '' then break
  426.            i = i + 1
  427.  
  428.            names.i = word(firstparam,words(firstparam))
  429.            types.i = left(firstparam,wordindex(firstparam,words(firstparam)) - 1)
  430.  
  431.            if substr(names.i,1,1) = '*' then do
  432.                names.i = strip(names.i,'l','*')
  433.                types.i = types.i'*'
  434.            end
  435.  
  436.            names.i = strip(names.i)
  437.            types.i = strip(types.i)
  438.         end
  439.  
  440.         call close(makeObjFile)
  441.  
  442.         call writech(output,indent || cppClassName '(')
  443.  
  444.         do j = 1 to i
  445.             call writech(output,types.j names.j)
  446.  
  447.             if j ~= i then writech(output,', ')
  448.             else writeln(output,')')
  449.         end
  450.  
  451.         call writeln(output,indent":" classPrefix || superClassName "()")
  452.         call writeln(output,indent'{')
  453.         call writech(output,indent || indent'object = MUI_MakeObject ('objectType', ')
  454.  
  455.         do j = 1 to i
  456.             call writech(output,names.j)
  457.  
  458.             if j ~= i then writech(output,', ')
  459.             else writeln(output,');')
  460.         end
  461.  
  462.         call writeln(output,indent'}'nl)
  463.     end
  464.  
  465. return
  466.  
  467. /* This function writes the attribute access functions and member functions
  468.    for a given class name */
  469.  
  470. WriteAttributesAndMethods: PROCEDURE expose output indent nl obsoleteName inlinesFile classPrefix obsoleteInlinesFile obsoleteDeclarationsFile obsoleteDeclarationsExist startVarArgs
  471.     parse arg className , superClassName
  472.  
  473.     getPrefix = ''      /* String used before get attribute method */
  474.     setPrefix = 'Set'   /* String used before set attribute method */
  475.  
  476.     /* Open muidefs file */
  477.  
  478.     if superClassName ~= '' then do
  479.         if ~open(defs,superClassName'.muidefs','read') then do
  480.             say "Could not open" superClassName'.muidefs'
  481.             return
  482.         end
  483.     end
  484.  
  485.     else if ~open(defs,className'.muidefs','read') then do
  486.         say "Could not open" className'.muidefs'
  487.         return
  488.     end
  489.  
  490.     cppClassName = classPrefix || className
  491.  
  492.     do while ~eof(defs)
  493.         line = readln(defs)
  494.  
  495.         /* Write attribute member functions */
  496.  
  497.         if word(line,1) = 'attribute' then do
  498.             parse var line _ tag name obsolete usage type
  499.             type = strip(type)
  500.  
  501.             if obsolete = 'O' then do
  502.                 fileForDeclarations = obsoleteDeclarationsFile
  503.                 fileForInlines = obsoleteInlinesFile
  504.                 obsoleteDeclarationsExist = 'y'
  505.             end
  506.  
  507.             else do
  508.                 fileForDeclarations = output
  509.                 fileForInlines = inlinesFile
  510.             end
  511.  
  512.             /* If getable write the get attribute method */
  513.  
  514.             if substr(usage,3,1) = 'G' then do
  515.                 name = getPrefix || name
  516.  
  517.                 call writeln(fileForDeclarations,indent || type name '(void) const;')
  518.  
  519.                 call writeln(fileForInlines,'inline' type cppClassName'::'name '(void) const'nl'{')
  520.                 call writeln(fileForInlines,indent "return ("type")GetAttr ("tag");")
  521.                 call writeln(fileForInlines,'}'nl)
  522.  
  523.                 call writeln(lib,type cppClassName'::'name '(void) const'nl'{')
  524.                 call writeln(lib,indent "return ("type")GetAttr ("tag");")
  525.                 call writeln(lib,'}'nl)
  526.             end
  527.  
  528.             /* If setable write the set attribute method */
  529.  
  530.             if substr(usage,2,1) = 'S' then do
  531.                 name = setPrefix || name
  532.  
  533.                 call writeln(fileForDeclarations,indent || 'void 'name '('type 'value);')
  534.  
  535.                 call writeln(fileForInlines,'inline void' cppClassName'::'name '('type 'value)'nl'{')
  536.                 call writeln(fileForInlines,indent "SetAttr ("tag", (ULONG)value);")
  537.                 call writeln(fileForInlines,'}'nl)
  538.  
  539.                 call writeln(lib,'void' cppClassName'::'name '('type 'value)'nl'{')
  540.                 call writeln(lib,indent "SetAttr ("tag", (ULONG)value);")
  541.                 call writeln(lib,'}'nl)
  542.             end
  543.         end
  544.  
  545.         /* Write member functions (methods) */
  546.  
  547.         else if word(line,1) = 'method' then do
  548.             parse var line _ tag name obsolete params
  549.  
  550.             if obsolete = 'O' then do
  551.                 fileForDeclarations = obsoleteDeclarationsFile
  552.                 fileForInlines = obsoleteInlinesFile
  553.                 obsoleteDeclarationsExist = 'y'
  554.             end
  555.  
  556.             else do
  557.                 fileForDeclarations = output
  558.                 fileForInlines = inlinesFile
  559.             end
  560.  
  561.             /* Create array of param types and names */
  562.  
  563.             i = 0
  564.             variableArgs = 'n'
  565.  
  566.             do forever
  567.                 parse var params firstparam ',' params
  568.  
  569.                 if firstparam = '' then break
  570.                 if strip(firstparam) = '/* ... */' then break
  571.                 i = i + 1
  572.  
  573.                 names.i = word(firstparam,words(firstparam))
  574.                 types.i = left(firstparam,wordindex(firstparam,words(firstparam)) - 1)
  575.  
  576.                 if substr(names.i,1,1) = '*' then do
  577.                     names.i = strip(names.i,'l','*')
  578.                     types.i = types.i'*'
  579.                 end
  580.  
  581.                 names.i = strip(names.i)
  582.                 types.i = strip(types.i)
  583.             end
  584.  
  585.             if strip(firstparam) = '/* ... */' then variableArgs = 'y'
  586.  
  587.             if right(strip(names.i),3) = '[1]' then do
  588.                 variableArgs = 'y'
  589.                 parse var names.i names.i '[1]'
  590.             end
  591.  
  592.             paramlist = ''
  593.             arglist = ''
  594.  
  595.             if i = 0 then paramlist = 'void'
  596.  
  597.             else do
  598.                 do j = 1 to i
  599.                     paramlist = paramlist types.j names.j','
  600.                     arglist = arglist',' names.j
  601.                 end
  602.  
  603.                 paramlist = strip(paramlist)
  604.                 paramlist = strip(paramlist,'t',',')
  605.             end
  606.  
  607.             if variableArgs = 'n' then do
  608.                 call writeln(fileForDeclarations,indent"ULONG" name '('paramlist');')
  609.  
  610.                 call writeln(fileForInlines,'inline ULONG' cppClassName'::'name '('paramlist')'nl'{')
  611.                 call writeln(fileForInlines,indent'return DoMethod ('tag || arglist');')
  612.                 call writeln(fileForInlines,'}'nl)
  613.  
  614.                 call writeln(lib,'ULONG' cppClassName'::'name '('paramlist')'nl'{')
  615.                 call writeln(lib,indent'return DoMethod ('tag || arglist');')
  616.                 call writeln(lib,'}'nl)
  617.             end
  618.  
  619.             else do
  620.                 paramlist = startVarArgs 'sva, 'paramlist', ...'
  621.  
  622.                 call writeln(fileForDeclarations,indent"ULONG" name '('paramlist');')
  623.  
  624.                 call writeln(fileForInlines,'inline ULONG' cppClassName'::'name '('paramlist')'nl'{')
  625.                 call writeln(fileForInlines,indent'sva.methodID = 'tag';')
  626.                 call writeln(fileForInlines,indent'return DoMethodA ((Msg)&sva);')
  627.                 call writeln(fileForInlines,'}'nl)
  628.  
  629.                 call writeln(lib,'ULONG' cppClassName'::'name '('paramlist')'nl'{')
  630.                 call writeln(lib,indent'sva.methodID = 'tag';')
  631.                 call writeln(lib,indent'return DoMethodA ((Msg)&sva);')
  632.                 call writeln(lib,'}'nl)
  633.             end
  634.         end
  635.     end
  636.  
  637.     call close(defs)
  638.  
  639. return
  640.  
  641.